package com.wlt.security;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;

/**
 * security的配置类
 * 并开启鉴权配置注解
 */
@Configuration
@EnableMethodSecurity
public class SecurityConfig
{
    /**
     * security 配置
     * @param http          定义处理器
     * @return              构建处理器
     * @throws Exception    抛出异常
     */
    @Bean
    protected SecurityFilterChain securityFilterChain (HttpSecurity http) throws Exception
    {
        // 自定义表单登录
        http.formLogin(
            form -> {
                form.usernameParameter("username")                  // 用户名项
                    .passwordParameter("password")                  // 密码项
                    .loginProcessingUrl("/admin/login")             // 登录提交路径
                    .successHandler(new MyLoginSuccessHandler())    // 登录成功处理
                    .failureHandler(new MyLoginFailureHandler());   // 登录失败处理
            }
        );
        
        // 权限拦截配置
        http.authorizeHttpRequests(
            authorize -> {
                authorize.requestMatchers("/login", "/admin/login").permitAll();    // 登录请求不需要认证
                authorize.anyRequest().authenticated();                                 // 其余请求都需要认证
            }
        );
        
        // 退出登录配置
        http.logout(
            logout -> {
                logout.logoutUrl("/admin/logout")                           // 注销路径
                      .logoutSuccessHandler(new MyLogoutSuccessHandler())   // 登出成功处理器
                      .clearAuthentication(true)                            // 清除认证数据
                      .invalidateHttpSession(true);                         // 清除session
            }
        );
        
        // 异常处理
        http.exceptionHandling(
            exception -> {
                exception.authenticationEntryPoint(new MyAuthenticationEntryPoint())    // 未登录处理器
                         .accessDeniedHandler(new MyAccessDeniedHandler());             // 权限不足处理器
            }
        );
        
        // 跨域访问
        http.cors();
        
        return http.build();
    }
    
    /**
     * 加密工具
     */
    @Bean
    public PasswordEncoder passwordEncoder ()
    {
        return new BCryptPasswordEncoder();
    }
}
